function varargout = TLSendercomspecDlg(action,varargin)

% TL_SENDERCOMSPEC_DLG manages the user interface for TargetLink SenderComSpec block
%
% SYNTAX dlgInfo = TLSendercomspecDlg('GetDlgInfo');
%   gets dialog info of TargetLink SenderComSpec block
%
%   INPUT ARGUMENTS
%   -/-      
%
%   OUTPUT ARGUMENTS
%   dlgInfo     dialog information contains pageNames etc.
%
% SYNTAX [sheetDims, ctrlPos] = TLSendercomspecDlg('CtrlPositions', pageName, commonGeom, dlgInfo, sheetDims);
%   calculates the control positions of all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometry data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%
%   OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% SYNTAX dlgdata = TLSendercomspecDlg('Create', pageName, dlgfig, dlgdata);
%   creates all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX [dlgdata,bModified] = TLSendercomspecDlg('Manage', pageName, dlgfig, dlgdata, pageAction);
%   manages all actions of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageAction      modified control of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%
% SYNTAX dlgdata = TLSendercomspecDlg('Update', dlgfig, dlgdata, pageNum);
%   updates all controls of dialog page: <pageNum>
%
%   INPUT ARGUMENTS
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageNum         number of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX TLSendercomspecDlg('Apply', dlgfig, dlgdata);
%   writes current blockdata to block and DD
%
%   INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
%   OUTPUT ARGUMENTS
%   - / -


% Author(s): D. Andoleit, T. Pietzsch
% $RCSfile: TLSendercomspecDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/SimulinkBlocksets/TLBlocksets/AUTOSARBlockset/AUTOSARBlockset_UI/Sources/MSrc/project.pj $
% $Revision: 1.14 $
% $Date: 2011/04/01 13:25:39MESZ $
%
% Copyright ?2011 dSPACE GmbH. All rights reserved.


switch action

    case 'GetDlgInfo'
        hBlock = varargin{1};
        dlgInfo = tl_get_dlginfodefaults('tlsim');
        titleName = 'SenderComSpec';
        pathinfo = tl_pathinfo(hBlock);
        dlgInfo.title = sprintf('TargetLink %s: %s', titleName, pathinfo.shortDisplayName);
        % no associated Simulink block
        dlgInfo.bSLParamDlg = 0;
        % no link to code
        dlgInfo.bEditCode = 0;
        dlgInfo.bViewCode = 0;
        % no plot signals
        dlgInfo.bPlotSignal = 0;
        dlgInfo.pageNames = {
            'ComSpec'...
            'Documentation'};
        varargout{1} = dlgInfo;
        varargout{2} = get_tlcg_data(hBlock);

    case 'CtrlPositions'
        pageName     = varargin{1};
        commonGeom   = varargin{2};
        sheetDims    = varargin{4};
        switch pageName
            case 'ComSpec'
                [sheetDims, ctrlPos] = FcnCalcComSpecControlPositions(commonGeom);
                
            case 'Documentation'
                bTblBlock = 0;
                bCodeComment = 0;
                [sheetDims,ctrlPos] = TLManageDocCtrls( ...
                    'ctrlpos', commonGeom, sheetDims, bCodeComment, bTblBlock);
        end
        varargout{1} = sheetDims;
        varargout{2} = ctrlPos;

    case 'Create'
        pageName = varargin{1};
        dlgfig   = varargin{2};
        dlgdata  = varargin{3};
        pageNum  = strmatch(pageName, dlgdata.pageNames, 'exact');
        switch pageName
            case 'ComSpec'
                % create all controls
                dlgdata = FcnCreateComSpecControls(pageNum,dlgfig,dlgdata);
                
            case 'Documentation'
                dlgdata = TLManageDocCtrls('create',pageNum,dlgfig,dlgdata);
        end
        dlgdata.pageData{pageNum}.ctrlPos = [];
        varargout{1} = dlgdata;

    case 'Manage',
        pageName   = varargin{1};
        dlgfig     = varargin{2};
        dlgdata    = varargin{3};
        pageAction = varargin{4};
        pageNum    = strmatch(pageName,dlgdata.pageNames,'exact');
        switch pageName
            case 'ComSpec'
                [dlgdata, bModified] = FcnManageComSpecControls(pageNum,dlgdata,pageAction);
                
            case 'Documentation'
                [dlgdata,bModified] = TLManageDocCtrls('callback',pageNum,dlgfig,dlgdata,pageAction);
        end
        varargout{1} = dlgdata;
        varargout{2} = bModified;

    case 'Update'
        dlgfig    = varargin{1};
        dlgdata   = varargin{2};
        pageNum   = varargin{3};

        pageName  = dlgdata.pageNames{pageNum};

        switch pageName
            case 'ComSpec'
                dlgdata = FcnUpdateComSpecControls(dlgdata,dlgfig,pageNum);
                
            case 'Documentation'
                TLManageDocCtrls('update', pageNum, dlgfig, dlgdata);
        end
        varargout{1} = dlgdata;

    case 'Apply'
        dlgdata  = varargin{2};
        bClose   = varargin{3};
        [dlgdata, bClose] = tl_apply_blockdata(dlgdata, bClose);
        varargout{1} = dlgdata;
        varargout{2} = bClose;

    otherwise
        error(['Invalid action "' action '"']);

end


%-----------------------------------------------------------------------------------------
% FcnCalcComSpecControlPositions calculates positions for all controls on gain page
%
% INPUT ARGUMENTS
%   commonGeom      common geometry information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnCalcComSpecControlPositions(commonGeom)

strings_and_styles = {...
    repmat('m',1,60),      'text'; ...
    repmat('m',1,20),      'checkbox'};

[comSpecTextSize, ...
    checkboxSize] = ...
    ds_get_uicontrol_sizes(commonGeom, strings_and_styles);

% Get the page partitioning and row/column spacing.
widths = comSpecTextSize(1);
[col,colWidth,colDelta,rowDelta] = ds_get_gui_columns(widths,commonGeom);

comSpecGroupboxWidth = col(end) + colWidth(end) + commonGeom.frameSideEdgeBuffer;
comSpecGroupboxHeight = ...
    commonGeom.frameTopEdgeBuffer ...
    + rowDelta ...
    + 2 * commonGeom.textHeight  ...
    + 3 * commonGeom.editHeight  ...
    + commonGeom.frameBottomEdgeBuffer;
cx = commonGeom.figSideEdgeBuffer + commonGeom.sheetSideEdgeBuffer;
cy = commonGeom.bottomSheetOffset + commonGeom.sheetBottomEdgeBuffer;
ctrlPos.comSpecGroupbox = [cx,cy,comSpecGroupboxWidth,comSpecGroupboxHeight];

% feedback checkbox
cy = commonGeom.frameBottomEdgeBuffer;
cx = col(1);

ctrlPos.feedbackCheckbox = [cx,cy,checkboxSize];

% RTE status checkbox
cy = cy + commonGeom.editHeight;
cx = col(1);

ctrlPos.rteStatusCheckbox = [cx,cy,checkboxSize];

% invalidate checkbox
cy = cy + commonGeom.editHeight;
cx = col(1);

ctrlPos.invalidateCheckbox = [cx,cy,checkboxSize];

% ComSpec
cy = cy + commonGeom.editHeight;
cx = col(1);
ctrlPos.comSpecText = [cx cy comSpecTextSize];
cy = cy + commonGeom.textHeight;
ctrlPos.clickText = [cx cy comSpecTextSize];

% Width and height of page.
width = comSpecGroupboxWidth + 2 * commonGeom.sheetSideEdgeBuffer;
height = ...
    commonGeom.textHeight ...
    + comSpecGroupboxHeight ...
    + commonGeom.sheetBottomEdgeBuffer;
sheetDims = [width height];


%-----------------------------------------------------------------------------------------
% FcnCreateComSpecControls creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateComSpecControls(pageNum,dlgfig,dlgdata)

Children = dlgdata.pageData{pageNum}.children;
ctrlPos  = dlgdata.pageData{pageNum}.ctrlPos;

% create the comSpecGroupbox
Children.comSpecGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'ComSpec'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.comSpecGroupbox);

% comSpec controls
Children.clickText = uicontrol( ...
    'Parent',             Children.comSpecGroupbox, ...
    'ForegroundColor',    'black', ...
    'Enable',             flag2str(dlgdata.bDSDDMan), ...
    'string', 'Data Dictionary ComSpec object (mouse click for editing): ', ...
    'Style',              'text', ...
    'Position',           ctrlPos.clickText);

Children.comSpecText = uicontrol( ...
    'Parent',             Children.comSpecGroupbox, ...
    'ForegroundColor',    'blue', ...
    'FontAngle',          'italic', ...
    'string',             ' ', ...
    'Style',              'text', ...
    'Position',           ctrlPos.comSpecText);

Children.invalidateCheckbox = uicontrol( ...
    'Parent',             Children.comSpecGroupbox, ...
    'Style',              'checkbox', ...
    'Value',              1, ...
    'String',             ' Add invalidate inport', ...
    'Position',           ctrlPos.invalidateCheckbox);

Children.rteStatusCheckbox = uicontrol( ...
    'Parent',             Children.comSpecGroupbox, ...
    'Style',              'checkbox', ...
    'Value',              1, ...
    'String',             ' Add RTE status port', ...
    'Position',           ctrlPos.rteStatusCheckbox);

Children.feedbackCheckbox = uicontrol( ...
    'Parent',             Children.comSpecGroupbox, ...
    'Style',              'checkbox', ...
    'Value',              1, ...
    'String',             ' Add feedback port', ...
    'Position',           ctrlPos.feedbackCheckbox);

set(Children.comSpecText,'ButtonDownFcn',@FcnTextClick);

dlgdata.pageData{pageNum}.children = Children;


%-----------------------------------------------------------------------------------------
% FcnTextClick manages button down action
%
% INPUT ARGUMENTS
%   src         handle of uicontrol
%   dummy_event <not used>
%
% OUTPUT ARGUMENTS
%   - / -
%-----------------------------------------------------------------------------------------
function FcnTextClick(dummy_src, dummy_event)   %#ok two arguments necessary

panel = get(dummy_src, 'Parent');
parent = get(panel, 'Parent');
dlgdata = get(parent, 'UserData');
if dlgdata.bDSDDMan
    % userData contains complete string, whereas text control string is cutted at the end if too long
    userData = get(dummy_src, 'UserData');
    comSpec = userData.ctrlStatus.string;
    if strncmp(comSpec,'<',1)
        comSpecRoot = userData.comSpecRootPath;
        dsddman('Select', comSpecRoot);
    else
        comSpecPath = ['/Pool/Autosar/SoftwareComponents/' comSpec];
        dsddman('Select', comSpecPath);
    end
else
    % do nothing
end


%-----------------------------------------------------------------------------------------
% FcnManageComSpecControls manage control actions of ComSpec page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageComSpecControls(pageNum,dlgdata,pageAction)

Children   = dlgdata.pageData{pageNum}.children;

switch pageAction
    case 'invalidateCheckbox'
        dlgdata.data.invalidate = get(Children.invalidateCheckbox,'Value');
        bModified = 1;

    case 'rteStatusCheckbox'
        dlgdata.data.rtestatus = get(Children.rteStatusCheckbox,'Value');
        bModified = 1;

    case 'feedbackCheckbox'
        dlgdata.data.feedback = get(Children.feedbackCheckbox,'Value');
        bModified = 1;

    otherwise
        bModified = 0;
        % do nothing
end


%-----------------------------------------------------------------------------------------
% FcnUpdateComSpecControls updates the controls of the ComSpec tab
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnUpdateComSpecControls(dlgdata, dlgfig, pageNum)

Children = dlgdata.pageData{pageNum}.children;
data = dlgdata.data;

if dlgdata.bIsFullVs
    enableOn = 'on';
else
    enableOn = 'inactive';
end
% default control status for controls
comSpecTextCtrlStatus = struct('enable', flag2str(dlgdata.bDSDDMan), 'string', dlgdata.data.comspec);
invalidateCheckboxCtrlStatus = struct('enable', enableOn, 'value', dlgdata.data.invalidate);    %#ok
rteStatusCheckboxCtrlStatus = struct('enable', enableOn, 'value', dlgdata.data.rtestatus);  %#ok
feedbackCheckboxCtrlStatus = struct('enable', enableOn, 'value', dlgdata.data.feedback);    %#ok
statusString = '';
data.comspec = '';
portPath = '/Pool/Autosar/SoftwareComponents';

% search for associated TL_Outport
objBlock = get_param(dlgdata.model, 'Object');
% get destination block of first output
hDstBlock = objBlock.portConnectivity(objBlock.Ports(1)+1).DstBlock;
if ~isempty(hDstBlock) && isempty(get_param(hDstBlock, 'MaskType')) && strcmp(get_param(hDstBlock, 'BlockType'), 'Outport')
    % Simulink outport in virtual subsystem
    objParent = get_param(get_param(hDstBlock, 'Parent'), 'Object');
    hDstBlock = objParent.portConnectivity(objParent.Ports(1)+1).DstBlock;
end
if ~isempty(hDstBlock) && numel(hDstBlock) == 1 ...
        && any(strcmp(get_param(hDstBlock, 'MaskType'), {'TL_Outport', 'TL_BusOutport'}))
    % get block data of associated outport
    outportData = get_tlcg_data(hDstBlock);
    if isfield(outportData, 'autosar') ...
            && outportData.autosar.useautosarcommunication == 1 ...
            && outportData.autosar.kind == 2
        objDstBlock = get_param(hDstBlock, 'Object');
        if objDstBlock.isValidProperty('SWC')
            swcPath = objDstBlock.SWC;
            portPath = ['/Pool/Autosar/SoftwareComponents/' swcPath '/Ports/' outportData.autosar.senderreceiverport];
            interfaceRef = dsdd('GetSenderReceiverInterfaceRef',portPath);
            if isempty(swcPath)
                statusString = 'Software component could not be found.';
            elseif isempty(outportData.autosar.senderreceiverport) || isempty(outportData.autosar.dataelement)
                statusString = 'AUTOSAR settings of port block are incomplete or invalid.';
            elseif isempty(interfaceRef)
                statusString = 'SenderReceiverInterfaceRef could not be found.';
            end
            elementPath = ['/Pool/Autosar/Interfaces/' interfaceRef '/DataElements/' outportData.autosar.dataelement];
            if dsdd('Exist',elementPath,'Property','IsQueued')
                % IsQueued property of data element determine comSpec kind
                bIsQueued = dsdd('GetIsQueued',elementPath);
            else
                bIsQueued = 0;
            end
            if bIsQueued
                hDDComspec = dsdd('FindRefs', portPath, 'target', elementPath, 'ObjectKind', 'EventSenderComSpec', 'Property', 'DataElementRef');
            else
                hDDComspec = dsdd('FindRefs', portPath, 'target', elementPath, 'ObjectKind', 'DataSenderComSpec', 'Property', 'DataElementRef');
            end
            if ~isempty(hDDComspec)
                data.comspec = strrep(dsdd('GetAttribute',hDDComspec,'Path'), '//DD0/Pool/Autosar/SoftwareComponents/', '');
            end
        end
    end
end
if ~isempty(data.comspec)
    comSpecTextCtrlStatus.string = data.comspec;
    % write current comspec if changed
    if ~strcmp(dlgdata.data.comspec, data.comspec)
        dummyData = dlgdata.olddata;
        dummyData.comspec = data.comspec;
        set_tlcg_data(dlgdata.model, dummyData);
    end
else
    comSpecTextCtrlStatus.string = '<no associated ComSpec object found>';
    % comSpecTextCtrlStatus.iserror = 1;
    userData = get(Children.comSpecText, 'UserData');
    if strcmp(portPath(end), '/')
        userData.comSpecRootPath = portPath(1:end-1);
    else
        userData.comSpecRootPath = portPath;
    end
    set(Children.comSpecText, 'UserData', userData);
end
dlgdata.data = data;

% write back control status of extra controls to the controls'
% UserData property
ctrlsList = {
    'comSpecText', ...
    'invalidateCheckbox', ...
    'rteStatusCheckbox' ...
    'feedbackCheckbox'};
for ctrlsNo=1:length(ctrlsList)
    ctrl = Children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
    set(ctrl, 'UserData', UserData);
end

% set control status of variable, scaling and gain parameter groupbox controls
TLSetCtrlsStatus(dlgfig,Children, ctrlsList)
set(dlgdata.SystemButtons.StatusLabel, 'String', statusString);

% simulate hyperlink
set(Children.comSpecText,'ForegroundColor','blue');
set(Children.comSpecText,'enable','inactive')
% set windowButtonMotionFcn if hyperlink exists
set(dlgfig, 'WindowButtonMotionFcn', {@FcnWindowButtonMotion, Children.comSpecText});


%-----------------------------------------------------------------------------------------
% FcnWindowButtonMotion manages the variable control callbacks
%
% INPUT ARGUMENTS
%   hObject         handle to figure1 (see GCBO)
%   eventdata       reserved - to be defined in a future version of MATLAB
%   hLink  handle of link control
%
% OUTPUT ARGUMENTS
%   - / -
%-----------------------------------------------------------------------------------------
function FcnWindowButtonMotion(hObject, eventdata, hLink)      %#ok<INUSL>

if ~isempty(hLink)
    cp = get(hObject, 'currentpoint');
    pos = get(hLink, 'position');
    posParent = get(get(hLink, 'parent'), 'position');
    pos(1:2) = pos(1:2) + posParent(1:2);
    bIsOverPosition = inpolygon(cp(1), cp(2), [pos(1) pos(1) pos(1)+pos(3) pos(1)+pos(3)], ...
        [pos(2) pos(2)+pos(4) pos(2)+pos(4) pos(2)]);
    if bIsOverPosition
        % set pointer to 'hand'
        set(hObject, 'Pointer', 'hand')
    else
        % reset pointer
        set(hObject, 'Pointer', 'arrow')
    end
end
